﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
using Org.BouncyCastle.Pkcs;//这是itext自带的，不需要单独添加BouncyCastle包
using System.IO;
using System.Data;


namespace HTToPdf
{
    class YFPDFPlus
    {
        Common Init = new Common();

        private static Document doc;
        private static PdfPTable table;
        string[] title;
        string[] content;

        float[] SetTotalWidth;//设定每列宽度
        int[] BorderSide;//设定每列边框
        int[] HAlign;
        string contents = "";
        string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory);
        Common.Model model = null;

        private static BaseFont titleBaseFont = BaseFont.CreateFont("C://WINDOWS//Fonts//simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);//黑体

        /// <summary>
        /// 创建PDF
        /// </summary>
        /// <param name="dtSource">数据源</param>
        /// <returns></returns>
        public bool CreatePDF(string SaveFileName,Common.Model model, DataTable dtSource)
        {
            this.model = model;
            bool flag = false;
            try
            {
                doc = new Document(PageSize.A4, 10, 10, 10, 10);//定义一个Document，并设置页面大小为A4，竖向
                MemoryStream pdfMS = new MemoryStream();
                PdfWriter writer = PdfWriter.GetInstance(doc, pdfMS);//PDF内容放入到流中
                doc.Open();

                PageHeader();

                int emptyRow = 10;//如果table的行数小于10行，那么剩余部分显示空白行
                int sortNo = 0;//序号
                int Total = 8;
                int erow = 0; //字数超过两行减1行文本空白框

                SetTotalWidth = new float[] { 25, 90, 80, 25, 55, 45, 70, 120, 70 };//设定每列宽度
                BorderSide = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };//设定每列边框
                //HAlign = new int[] { Element.ALIGN_CENTER, Element.ALIGN_CENTER, Element.ALIGN_CENTER, Element.ALIGN_CENTER, Element.ALIGN_CENTER, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, Element.ALIGN_MIDDLE, Element.ALIGN_LEFT };
                HAlign = new int[] { Element.ALIGN_CENTER, Element.ALIGN_CENTER, Element.ALIGN_CENTER, Element.ALIGN_CENTER, Element.ALIGN_RIGHT, Element.ALIGN_RIGHT, Element.ALIGN_RIGHT, Element.ALIGN_MIDDLE, Element.ALIGN_LEFT };
                if (dtSource.Rows.Count > 0)
                {
                    for (int i = 0; i < dtSource.Rows.Count; i++)
                    {
                        if (i % Total == 0 && i != 0)
                        {
                            PageFooter();
                            doc.NewPage();
                            PageHeader();
                        }

                        sortNo++;

                        if (dtSource.Rows[i]["shengccj"].ToString().Length > 26)
                        {
                            erow++;
                        }
                        string other = 
                        dtSource.Rows[i]["pihao"].ToString() + "/"
                        + dtSource.Rows[i]["baozhiqi"].ToString() + "/"
                        + dtSource.Rows[i]["sxrq"].ToString();
                        
                        content = new string[] { (i + 1).ToString(), dtSource.Rows[i]["spmch"].ToString(), dtSource.Rows[i]["shpgg"].ToString(), dtSource.Rows[i]["dw"].ToString(), dtSource.Rows[i]["shl"].ToString(), dtSource.Rows[i]["dj"].ToString(), dtSource.Rows[i]["hsje"].ToString(), dtSource.Rows[i]["shengccj"].ToString(), other };
                        table = AddTableHeader(content, SetTotalWidth, BorderSide, new Font(titleBaseFont, 8), HAlign);
                        doc.Add(table);
                    }
                }
                if (dtSource.Rows.Count % Total != 0)//说明数据源不足10行
                {
                    emptyRow = Total - dtSource.Rows.Count % Total - erow;//如果为负数，说明不需要生成空白行
                    for (int i = 0; i < emptyRow; i++)
                    {
                        content = new string[] { (dtSource.Rows.Count + i + 1).ToString(), "", "", "", "", "", "", "", "" };
                        table = AddTableHeader(content, SetTotalWidth, BorderSide, new Font(titleBaseFont, 8), HAlign);
                        doc.Add(table);
                    }
                }

                PageFooter();

                // doc.NewPage();//分页
                doc.Close();

                //保存pdf文件
                /*
                byte[] fileByte = pdfMS.GetBuffer();
                string fileName = @Guid.NewGuid().ToString() + ".pdf";
                FileStream fs = new FileStream(fileName, FileMode.Create);
                BinaryWriter bw = new BinaryWriter(fs);
                bw.Write(fileByte);
                bw.Close();
                fs.Close();
                if (SetImgWaterMark(@"sitamp.dll", fileName, SaveFileName))
                {
                    if (File.Exists(fileName))
                    {
                        File.Delete(fileName);
                    }
                    flag = true;
                }
                 */
                byte[] fileByte = pdfMS.GetBuffer();
                FileStream fs = new FileStream(SaveFileName, FileMode.Create);
                BinaryWriter bw = new BinaryWriter(fs);
                bw.Write(fileByte);
                bw.Close();
                fs.Close();
                flag = true;
            }
            catch (Exception ex)
            {
                Init.WriteLog(ex.ToString(), true);
            }
            return flag;
        }

        #region 文件头
        public void PageHeader()
        {

            HAlign = new int[] { Element.ALIGN_RIGHT, Element.ALIGN_LEFT, Element.ALIGN_RIGHT, Element.ALIGN_LEFT, Element.ALIGN_RIGHT, Element.ALIGN_LEFT, Element.ALIGN_RIGHT };
            BorderSide = new int[] { 15, 13 };//设定每列边框
            CreateEmptyRow(1);//生成一行空行
            AddHeaderTitleContent("四川金仁医药集团有限公司预付款采购合同", 1, 15, Font.BOLD);//添加表头
            CreateEmptyRow(1);//生成一行空行
            SetTotalWidth = new float[] { 480, 100, };//设定每列宽度 
            content = new string[] { "合同号：", model.djbh };
            table = AddTableHeader(content, SetTotalWidth, BorderSide, new Font(titleBaseFont, 10), HAlign);
            doc.Add(table);
            SetTotalWidth = new float[] { 160, 420, };//设定每列宽度                
            content = new string[] { "供货方（以下简称甲方）：", model.dwmch };
            table = AddTableHeader(content, SetTotalWidth, BorderSide, new Font(titleBaseFont, 10), HAlign);
            doc.Add(table);
            content = new string[] { "购买方（以下简称乙方）：", "四川金仁医药集团有限公司", };
            table = AddTableHeader(content, SetTotalWidth, BorderSide, new Font(titleBaseFont, 10), HAlign);
            doc.Add(table);
            contents = "  一、甲方销售商品的品名、规格、生产单位、数量、单价、总金额等规定如下表（最终以乙方确认收货的单据及甲方开出的销售票据和发票为准）。\r\n\r\n";
            AddHeaderTitleContent(contents, 0, 8, Font.NORMAL);//添加表头                

            content = new string[] { "序号", "商品名称", "商品规格", "单位", "数量", "单价", "金额", "生产企业", "批号/产期/效期" };
            //SetTotalWidth = new float[] { 25, 90, 80, 25, 60, 50, 60, 120, 70 };//设定每列宽度
            SetTotalWidth = new float[] { 25, 90, 80, 25, 55, 45, 70, 120, 70 };//设定每列宽度
            BorderSide = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };//设定每列边框
            HAlign = new int[] { Element.ALIGN_CENTER, Element.ALIGN_CENTER, Element.ALIGN_CENTER, Element.ALIGN_CENTER, Element.ALIGN_RIGHT, Element.ALIGN_RIGHT, Element.ALIGN_RIGHT, Element.ALIGN_MIDDLE, Element.ALIGN_LEFT };
            table = AddTableHeader(content, SetTotalWidth, BorderSide, new Font(titleBaseFont, 9), HAlign);
            doc.Add(table);
        }
        #endregion

        #region 文件尾
        public void PageFooter()
        {
            SetTotalWidth = new float[] { 75, 140, 75, 75, 140, 75 };//设定每列宽度
            BorderSide = new int[] { 0, 0, 0, 0, 0, 0 };//设定每列边框
            HAlign = new int[] { Element.ALIGN_RIGHT, Element.ALIGN_LEFT, Element.ALIGN_RIGHT, Element.ALIGN_RIGHT, Element.ALIGN_LEFT, Element.ALIGN_RIGHT };
            content = new string[] { "合计金额：", Init.NumtoChinese(decimal.Parse(model.hsje)), model.hsje,"折扣金额：", Init.NumtoChinese(decimal.Parse(model.zkzrje)), model.zkzrje};
            table = AddTableHeader(content, SetTotalWidth, BorderSide, new Font(titleBaseFont, 9), HAlign);
            doc.Add(table);
            /*
            if (!string.IsNullOrEmpty(model.zkzrje))
            {
                SetTotalWidth = new float[] { 115, 205, 70, 190 };//设定每列宽度
                BorderSide = new int[] { 0, 0, 0, 0 };//设定每列边框
                HAlign = new int[] { Element.ALIGN_RIGHT, Element.ALIGN_LEFT, Element.ALIGN_RIGHT, Element.ALIGN_LEFT };
                content = new string[] { "折扣金额：", Init.NumtoChinese(decimal.Parse(model.zkzrje)), model.zkzrje, "" };
                table = AddTableHeader(content, SetTotalWidth, BorderSide, new Font(titleBaseFont, 9), HAlign);
                doc.Add(table);
            }
            */
            SetTotalWidth = new float[] { 115, 205,70,190 };//设定每列宽度
            BorderSide = new int[] { 0, 0,0,0 };//设定每列边框
            HAlign = new int[] { Element.ALIGN_RIGHT, Element.ALIGN_LEFT, Element.ALIGN_RIGHT, Element.ALIGN_LEFT };
            content = new string[] { "实付金额：", Init.NumtoChinese(decimal.Parse(model.hsje) - decimal.Parse(model.zkzrje)), (decimal.Parse(model.hsje) - decimal.Parse(model.zkzrje)).ToString(), "" };
            table = AddTableHeader(content, SetTotalWidth, BorderSide, new Font(titleBaseFont, 9), HAlign);
            doc.Add(table);




           // CreateEmptyRow(1);//生成一行空行
            contents =
                      "  二、甲、乙双方需相互提供：企业营业执照、药品生产经营许可证或药品经营许可证及其它相关资质等有效证件复印件并加盖鲜章。\r\n"
                    + "  三、本合同项下货款是经甲、乙双方签订此合同后由乙方支付至甲方指定银行账户。\r\n";
            AddHeaderTitleContent(contents, 0, 8, Font.NORMAL);//添加表头

             title = new string[] { "四、甲方在收到乙方货款后应在", "日内向乙方送达所预付款项下的货物。\r\n" };
             content = new string[] { model.fhzq, "" };
             AddPartnerContent(title, content);
             title = new string[] { "五、本合同项下货物，未经乙方书面通知，甲方不得以任何理由发往他处。\r\n" };
             content = new string[] { "" };
             AddPartnerContent(title, content);
            title = new string[] { "六、验收及异议：乙方在收货后按销售票据或发票记载数量、规格等现场验收，对品种、数量、规格及外包装有异议的应当提出异议，"
                +"对产品质量有异议的应于收货后15日内书面提出异议，甲方应当在收到乙方异议后", "日内进行换货或补发。甲方对质保期内的产品质量负责。\r\n" };
            content = new string[] { model.yyzq, "" };
            AddPartnerContent(title, content);

            string[] Titlen = new string[] { "七、合理消耗：商品损耗按商品运输有关规定，因运输过程产生商品损耗的，由乙方出具破损说明书交甲方办理退换或补货手续。甲方应在收到乙方说明后", "日内进行退换或补发。\r\n" };
            string[] Contentn = new string[] { model.yyzq, "" };

                         AddPartnerContent(Titlen, Contentn);
            //AddHeaderTitleContent(contents, 0, 8, Font.NORMAL);//添加表头
            //AddPartnerContent("八、发货方式：", header[4]+"，代办托运运费由"+header[5]+"承担。运费及货物运输过程中的风险由甲方承担，在有效期内甲方负责退换货义务。");
            title = new string[] { "八、交货地点：乙方仓库。发货方式：", "运费及货物运输过程中的风险由甲方承担，在有效期内甲方有按照乙方要求进行退换货的义务。" };
          // content = new string[] { model.thfs, model.yunfcd, "" };
                         content = new string[] { model.thfs,""};
           AddPartnerContent(title, content);
            
            AddPartnerContent("九、结算期限：", model.jsms + "。");
            AddPartnerContent("十、支付方式：", model.fkfs + "。");
            contents =
                      "  十一、甲方未按本合同约定时间发货，则每逾期一天，甲方按所收到乙方货款金额的0.8％/天向乙方支付逾期违约金；超过15日仍未发货给乙方，甲方除向乙方支付逾期违约金外，还应按乙方向甲方支付货款金额的30％向乙方支付违约金。\r\n"
                    + "  十二、甲方所发货物距离生产日期不得超过三个月，否则乙方有权要求甲方无条件退换相关货品。\r\n"
                    + "  十三、甲方质量保证：1、药品质量符合法定质量标准和有关质量要求；2、药品附每批次质检报告书和产品合格证；3、进口药品附口岸药检报告；4、药品包装符合有关规定和货物运输要求。若出现质量问题（包括包装、说明书等问题），由甲方负责相应法律责任，并对由此造成的乙方一切损失承担赔偿责任。\r\n"
                    + "  十四、本合同所称乙方损失包括直接损失及间接损失，包括但不限于生产经营损失、预期利益损失、商誉受损损失，向第三方支付的违约金、赔偿金、处罚金等，及因处理纠纷支付的合理费用（律师费、保全费、差旅费、取证费、诉讼费等）等。\r\n"
                    + "  十五、甲方签约代表愿意对甲方所收到乙方预付货款向乙方提供连带保证责任担保，期限五年。\r\n"
                    + "  十六、本合同如发生争议，由甲、乙双方协商解决，协商不成的由乙方所在地人民法院管辖。\r\n"
                    + "  十七、甲、乙双方签约代表，对以上条款已阅读并同意。\r\n"
                    + "  十八、本合同一式三份，经双方签字、盖章后生效。本合同未尽事宜由双方签订补充协议进行约定，补充协议与本合同具有同等法律效力。\r\n"
                    + "";
            AddHeaderTitleContent(contents, 0, 8, Font.NORMAL);//添加表头
            AddHeaderTitleContent("合同签订日期：" + model.rq + "\r\n\r\n", 2, 8, Font.NORMAL);//添加表头
            SetTotalWidth = new float[] { 100, 190, 100, 190 };//设定每列宽度
            BorderSide = new int[] { 0, 0, 0, 0 };//设定每列边框
            HAlign = new int[] { Element.ALIGN_RIGHT, Element.ALIGN_LEFT, Element.ALIGN_RIGHT, Element.ALIGN_LEFT };
            content = new string[] { "供方（章）", model.dwmch, "购方（章）", "四川金仁医药集团有限公司" };
            table = AddTableHeader(content, SetTotalWidth, BorderSide, new Font(titleBaseFont, 12), HAlign);
            doc.Add(table);

            string[] tablelist = { "地址", "开户银行", "账号", "统一信用代码", "联系电话", "授权签约人" };
            string[] myvalue = { "成都市金牛区金丰路112号六幢1、2、3、4层5、6号", "四川天府银行股份有限公司成都金牛支行", "651001732000000168", "91510106768621824L", "028-83420240",model.username };
            string[] cutvalue = { model.dzhdh, model.khyh, model.yhzhh, model.shh, "", "" };

            for (int i = 0; i < tablelist.Count(); i++)
            {
                content = new string[] { tablelist[i], cutvalue[i], tablelist[i], myvalue[i] };
                table = AddTableHeader(content, SetTotalWidth, BorderSide, new Font(titleBaseFont, 12), HAlign);
                doc.Add(table);
            }
            iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(@path+"\\sitamp.dll");
            img.SetAbsolutePosition((doc.PageSize.Width / 2) + 110, (doc.PageSize.Height / 2) - 340);
            img.ScaleToFit(110F, 110F);
            //img.GrayFill = 20;
            doc.Add(img);
        }
        #endregion

        #region 生成水印
        /// <summary>
        /// 设置pdf图片水印
        /// </summary>
        /// <param name="imgPath">水印图片路径</param>
        /// <param name="filePath">需要添加水印的pdf文件</param>
        /// <param name="outfilePath">添加完成的pdf文件</param>
        /// <returns></returns>
        public static bool SetImgWaterMark(string imgPath, string filePath, string outfilePath)
        {
            PdfReader pdfReader = null;
            PdfStamper pdfStamper = null;
            FileStream fileStream = null;
            try
            {
                pdfReader = new PdfReader(filePath);
                fileStream = new FileStream(outfilePath, FileMode.Create);
                pdfStamper = new PdfStamper(pdfReader, fileStream);
                int total = pdfReader.NumberOfPages;
                Rectangle psize = pdfReader.GetPageSize(1);
                float width = psize.Width;
                float height = psize.Height;
                PdfContentByte content;
                //获取水印图片
                Image image = Image.GetInstance(imgPath);
                image.SetAbsolutePosition((doc.PageSize.Width / 2) - 150, (doc.PageSize.Height / 2) - 340);
                image.ScaleToFit(110F, 110F);
                image.GrayFill = 20;

                for (int i = 1; i <= total; i++)
                {
                    content = pdfStamper.GetOverContent(i);//在内容上方加水印
                    //content = pdfStamper.GetUnderContent(i);//在内容下方加水印
                    content.AddImage(image);
                }
                return true;
            }
            catch (Exception ex)
            {
                //Common.WriteLogs(ex.ToString(), true);
                outfilePath = "";
                return false;
            }
            finally
            {
                if (pdfStamper != null)
                {
                    pdfStamper.Close();
                }
                if (pdfReader != null)
                {
                    pdfReader.Close();
                }
                if (fileStream != null)
                {
                    fileStream.Close();
                    fileStream.Dispose();
                }
            }
        }
        #endregion


        #region 生成N行空白行
        private static void CreateEmptyRow(int emptyRowNum)
        {
            for (int i = 0; i < emptyRowNum; i++)
            {
                doc.Add(new Paragraph(" "));
            }
        }
        #endregion

        #region 生成标题
        /// <summary>
        /// 
        /// </summary>
        /// <param name="content">内容</param>
        /// <param name="Alignment">对齐 0居左，1居中，2居右</param>
        /// <param name="FontSize">字体大小</param>
        /// <param name="style">样式</param>
        private static void AddHeaderTitleContent(string content, int Alignment, int FontSize, int style)
        {
            Paragraph p = new Paragraph(content, new Font(titleBaseFont, FontSize, style));
            p.Alignment = Alignment;
            doc.Add(p);
        }
        #endregion

        #region 生成表格头
        private static PdfPTable AddTableHeader(string[] content, float[] colSet, int[] BorderSide, Font font, int[] horizontalAlignment)
        {
            int count = content.Count();
            PdfPTable table = new PdfPTable(count);//列的table
            //添加表格列头               
            //table.SetTotalWidth(SetTotalWidth);
            table.SetWidthPercentage(colSet, PageSize.A4);
            for (int i = 0; i < count; i++)
            {
                table.AddCell(GetPdfCell(content[i], font, horizontalAlignment[i], BorderSide[i]));
            }
            return table;
        }
        #endregion

        #region 生成单元格
        private static PdfPCell GetPdfCell(string content, Font font, int horizontalAlignment, int BorderSide)
        {
            PdfPCell cell = new PdfPCell(new Paragraph(content, font));
            cell.HorizontalAlignment = horizontalAlignment;//水平位置
            cell.VerticalAlignment = Element.ALIGN_CENTER;//垂直居中
            cell.MinimumHeight = 18;//单元格的最小高度
            cell.NoWrap = false;
            cell.DisableBorderSide(BorderSide);
            return cell;
        }
        #endregion

        //四种字体
        private static Font fontMiddle = new Font(titleBaseFont, 8, Font.BOLD);
        private static Font fontSmallNoBold = new Font(titleBaseFont, 8);
        private static float IndentationLeft = 10;//距左边距

        private static void AddPartnerContent(string Title, string Content)
        {
            fontMiddle.SetStyle(Font.UNDERLINE);//文字下划线
            Paragraph content = new Paragraph();
            content.IndentationLeft = IndentationLeft;
            Chunk chunkName = new Chunk(Title, fontSmallNoBold);
            Chunk chunkText;
            if (string.IsNullOrEmpty(Content) || Content == "。")
            {
                chunkText = new Chunk(GetEmptyString(6, " /。 "), fontMiddle);
            }
            else
            {
                chunkText = new Chunk(GetEmptyString(Content.Length + 6, Content), fontMiddle);
            }
            content.Add(0, chunkName);
            content.Add(1, chunkText);
            content.Alignment = 3;
            doc.Add(content);
        }
        private static void AddPartnerContent(string[] Title, string[] Content)
        {
            fontMiddle.SetStyle(Font.UNDERLINE);//文字下划线
            Paragraph content = new Paragraph();
            content.IndentationLeft = IndentationLeft;
            int Total = 0;
            for (int i = 0; i < Title.Count(); i++)
            {
                Chunk chunkName = new Chunk(Title[i], fontSmallNoBold);
                Chunk chunkText = string.IsNullOrEmpty(Content[i]) ? new Chunk(GetEmptyString(0, ""), fontMiddle) : new Chunk(GetEmptyString(Content[i].Length + 6, Content[i]), fontMiddle);
                content.Add(Total, chunkName);
                Total++;
                content.Add(Total, chunkText);
                Total++;
            }
            content.Alignment = 3;
            doc.Add(content);
        }
        //居中显示内容
        private static string GetEmptyString(int maxlength, string text)
        {
            int padding = (maxlength - text.Length * 2) / 2;
            string empty = string.Empty;
            for (int i = 0; i < padding; i++)
            {
                empty += " ";
            }
            return string.Format("{0}{1}{0}", empty, text);
        }

        static string pfxPath = "001180530510644.pfx";
        static string pfxPwd = "111111";
        static string sourcePdf = "template.pdf";
        static string imgPath = "password_1.png";
        public static void PDFSignWithIText5Demo()
        {
            string outPutPdf = "ImageStampWithIText5.pdf";
            var reader = new iTextSharp.text.pdf.PdfReader(sourcePdf);
            using (FileStream fs = new FileStream(outPutPdf, FileMode.Create))
            {
                var stamper = iTextSharp.text.pdf.PdfStamper.CreateSignature(reader, fs, '\0', null, true);
                var appearance = stamper.SignatureAppearance;
                appearance.Reason = "签名测试原因";
                appearance.Location = "签名位置";
                appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(200, 200, 300, 300), 1, "itext");
                //itext会自动对图片进行等比例缩放
                appearance.SignatureGraphic = iTextSharp.text.Image.GetInstance(imgPath);
                appearance.CertificationLevel = iTextSharp.text.pdf.PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED;
                appearance.SignatureRenderingMode = iTextSharp.text.pdf.PdfSignatureAppearance.RenderingMode.GRAPHIC;


                using (var stream = File.OpenRead(pfxPath))
                {
                    Pkcs12Store store = new Pkcs12Store(stream, pfxPwd.ToCharArray());
                    string keyAlias = null;
                    foreach (string alias in store.Aliases)
                    {
                        keyAlias = alias;
                        break;
                    }
                    var chains = store.GetCertificateChain(keyAlias).Select(c => c.Certificate).ToList();
                    var signature = new PrivateKeySignature(store.GetKey(keyAlias).Key, DigestAlgorithms.SHA1);
                    MakeSignature.SignDetached(appearance, signature, chains, null, null, null, 0, CryptoStandard.CADES);
                }
            }
        }
    }
}